home *** CD-ROM | disk | FTP | other *** search
/ Amiga Games Extra 1996 September / Amiga Games Extra CD-ROM 9-1996.iso / userbox / publicdomain / vim-4.2 / src / archie.c < prev    next >
C/C++ Source or Header  |  1996-06-09  |  15KB  |  818 lines

  1. /* vi:set ts=4 sw=4:
  2.  *
  3.  *
  4.  * VIM - Vi IMproved
  5.  *
  6.  * Code Contributions By:    Bram Moolenaar            mool@plex.nl
  7.  *                            Tim Thompson            twitch!tjt
  8.  *                            Tony Andrews            onecom!wldrdg!tony 
  9.  *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  10.  */
  11. /*
  12.  * archie.c -- RISC OS + UnixLib specific code.
  13.  *
  14.  * A lot of this file was written by Juergen Weigert.
  15.  *
  16.  * It was then hacked to pieces by Alun Jones to work on the Acorn
  17.  * Archimedes!
  18.  */
  19.  
  20. #include "vim.h"
  21. #include "globals.h"
  22. #include "option.h"
  23. #include "proto.h"
  24.  
  25. #ifdef HAVE_FCNTL_H
  26. # include <fcntl.h>
  27. #endif
  28. #include <time.h>
  29. #include <unistd.h>
  30. #include <sys/types.h>
  31. #include <sys/os.h>
  32. #include <signal.h>
  33.  
  34. #include <termio.h>
  35.  
  36. static int    Read __ARGS((char *, long));
  37. static int    WaitForChar __ARGS((long));
  38. static int    RealWaitForChar __ARGS((long));
  39. static void fill_inbuf __ARGS((void));
  40. static int    have_wildcard __ARGS((int, char **));
  41.  
  42. static int do_resize = FALSE;
  43.  
  44. /* I'm sure this should be defined in UnixLib, but it ain't!
  45.  */
  46. short ospeed;
  47.  
  48.     void
  49. mch_write(s, len)
  50.     char    *s;
  51.     int        len;
  52. {
  53.     int i;
  54.     for (i=0; i<len; i++)
  55.     {
  56.         os_vdu(s[i]);
  57.     }
  58. }
  59.  
  60. /*
  61.  * mch_inchar(): low level input funcion.
  62.  * Get a characters from the keyboard.
  63.  * If time == 0 do not wait for characters.
  64.  * If time == n wait a short time for characters.
  65.  * If time == -1 wait forever for characters.
  66.  */
  67.     int
  68. mch_inchar(buf, maxlen, time)
  69.     char    *buf;
  70.     int        maxlen;
  71.     long    time;
  72. {
  73.     if (time >= 0)
  74.     {
  75.         if (WaitForChar(time) == 0)        /* no character available */
  76.             return 0;
  77.     }
  78.     else        /* time == -1 */
  79.     {
  80.     /*
  81.      * If there is no character available within 2 seconds (default)
  82.      * write the autoscript file to disk
  83.      */
  84.         if (WaitForChar(p_ut) == 0)
  85.             updatescript(0);
  86.     }
  87.  
  88.     WaitForChar(-1L);
  89.     return Read(buf, (long)maxlen);
  90. }
  91.  
  92.     void
  93. mch_delay(msec, ignoreinput)
  94.     long    msec;
  95.     int        ignoreinput;
  96. {
  97.     clock_t    now;
  98.  
  99.     if (ignoreinput)
  100.     {
  101.         now = clock();
  102.         while (clock() < now + (msec * CLOCKS_PER_SEC) / 1000)
  103.             ;
  104.     }
  105.     else
  106.         WaitForChar(msec);
  107. }
  108.  
  109. /*
  110.  * No job control. Fake it by starting a new shell.
  111.  */
  112.     void
  113. mch_suspend()
  114. {
  115.     MSG_OUTSTR("new shell started\n");
  116.     call_shell(NULL, SHELL_COOKED);
  117.     need_check_timestamps = TRUE;
  118. }
  119.  
  120.     void
  121. mch_windinit()
  122. {
  123.     Columns = 80;
  124.     Rows = 24;
  125.  
  126.     flushbuf();
  127.  
  128.     mch_get_winsize();
  129. }
  130.  
  131. /*
  132.  * mch_check_win checks whether we have an interactive window.
  133.  */
  134.     int
  135. mch_check_win(argc, argv)
  136.     int argc;
  137.     char **argv;
  138. {
  139.     if (isatty(1))
  140.         return OK;
  141.     return FAIL;
  142. }
  143.  
  144. /*
  145.  * Return OK if the input comes from a terminal, FAIL otherwise.
  146.  */
  147.     int
  148. mch_check_input()
  149. {
  150.     if (isatty(0))
  151.         return OK;
  152.     return FAIL;
  153. }
  154.  
  155. /*
  156.  * fname_case(): Set the case of the filename, if it already exists.
  157.  *                 This will cause the filename to remain exactly the same.
  158.  */
  159.     void
  160. fname_case(name)
  161.     char *name;
  162. {
  163. }
  164.  
  165.     void
  166. mch_settitle(str)
  167.     char *str;
  168. {
  169. }
  170.  
  171.     void
  172. mch_resettitle()
  173. {
  174. }
  175.  
  176.     int
  177. mch_can_restore_title()
  178. {
  179.     return FALSE;
  180. }
  181.  
  182.     int
  183. mch_can_restore_icon()
  184. {
  185.     return FALSE;
  186. }
  187.  
  188. /*
  189.  * Insert user name in s[len].
  190.  */
  191.     int
  192. mch_get_user_name(s, len)
  193.     char_u    *s;
  194.     int        len;
  195. {
  196.     *s = NUL;
  197.     return FAIL;
  198. }
  199.  
  200. /*
  201.  * Insert host name is s[len].
  202.  */
  203.     void
  204. mch_get_host_name(s, len)
  205.     char_u    *s;
  206.     int        len;
  207. {
  208.     STRNCPY(s, "Archimedes", len);
  209. }
  210.  
  211. /*
  212.  * return process ID
  213.  */
  214.     long
  215. mch_get_pid()
  216. {
  217.     return (long)0;
  218. }
  219.  
  220. /*
  221.  * Get name of current directory into buffer 'buf' of length 'len' bytes.
  222.  * Return non-zero for success.
  223.  */
  224.     int 
  225. dirname(buf, len)
  226.     char *buf;
  227.     int len;
  228. {
  229.     extern int        errno;
  230.     extern char        *sys_errlist[];
  231.  
  232.     if (getcwd(buf,len) == NULL)
  233.     {
  234.         strcpy(buf, sys_errlist[errno]);
  235.         return 0;
  236.     }
  237.     return 1;
  238. }
  239.  
  240. /*
  241.  * get absolute filename into buffer 'buf' of length 'len' bytes
  242.  */
  243.     int 
  244. FullName(fname, buf, len, force)
  245.     char *fname, *buf;
  246.     int len;
  247.     int force;
  248. {
  249.     int        l;
  250.     char    olddir[MAXPATHL];
  251.     char    *p;
  252.     int        c;
  253.     int        retval = 1;
  254.  
  255.     if (fname == NULL)    /* always fail */
  256.         return 0;
  257.  
  258.     *buf = 0;
  259.     if (force || *fname != '/')
  260.     {
  261.         /*
  262.          * If the file name has a path, change to that directory for a moment,
  263.          * and then do the getwd() (and get back to where we were).
  264.          * This will get the correct path name with "../" things.
  265.          */
  266.         if ((p = vim_strrchr((char_u *)fname, '/')) != NULL)
  267.         {
  268.             if (getcwd(olddir, MAXPATHL) == NULL)
  269.             {
  270.                 p = NULL;        /* can't get current dir: don't chdir */
  271.                 retval = 0;
  272.             }
  273.             else
  274.             {
  275.                 c = *p;
  276.                 *p = NUL;
  277.                 vim_chdir("\\");        /* Try to maintain PSD */
  278.                 if (vim_chdir(fname))
  279.                     retval = 0;
  280.                 else
  281.                     fname = p + 1;
  282.                 *p = c;
  283.             }
  284.         }
  285.         if (getcwd(buf, len) == NULL)
  286.         {
  287.             retval = 0;
  288.             *buf = NUL;
  289.         }
  290.         l = strlen(buf);
  291.         if (l && buf[l - 1] != '/')
  292.             strcat(buf, "/");
  293.         if (p)
  294.         {
  295.             vim_chdir("\\");            /* Maintain PSD */
  296.             vim_chdir(olddir);
  297.         }
  298.     }
  299.     strcat(buf, fname);
  300.     return retval;
  301. }
  302.  
  303. /*
  304.  * get file permissions for 'name'
  305.  */
  306.     long 
  307. getperm(name)
  308.     char *name;
  309. {
  310.     struct stat statb;
  311.  
  312.     if (stat(name, &statb))
  313.         return -1;
  314.     return statb.st_mode;
  315. }
  316.  
  317. /*
  318.  * set file permission for 'name' to 'perm'
  319.  */
  320.     int
  321. setperm(name, perm)
  322.     char *name;
  323.     int perm;
  324. {
  325.     return chmod(name, perm);
  326. }
  327.  
  328. /*
  329.  * return FALSE if "name" is not a directory
  330.  * return TRUE if "name" is a directory.
  331.  * return FALSE for error.
  332.  */
  333.     int 
  334. mch_isdir(name)
  335.     char *name;
  336. {
  337.     struct stat statb;
  338.  
  339.     if (stat(name, &statb))
  340.         return FALSE;
  341.     return ((statb.st_mode & S_IFMT) == S_IFDIR) ? TRUE : FALSE;
  342. }
  343.  
  344.     void
  345. mch_windexit(r)
  346.     int r;
  347. {
  348.     settmode(0);
  349.     stoptermcap();
  350.     flushbuf();
  351.     stopscript();                    /* remove autoscript file */
  352.     exit(r);
  353. }
  354.  
  355.     void
  356. mch_settmode(raw)
  357.     int                raw;
  358. {
  359.     static    int old225, old226, old4;
  360.     int        retvals[3];
  361.     static struct termio told;
  362.            struct termio tnew;
  363.  
  364.     if (raw)
  365.     {
  366.         /* Make arrow keys act as function keys.
  367.          */
  368.         os_byte(4, 2, 0, retvals);
  369.         old4 = retvals[1];
  370.         /* Now make function keys return NULL followed by a character.
  371.          * Remember the old value for resetting.
  372.          */
  373.         os_byte(225, 0xC0, 0, retvals);
  374.         old225 = retvals[1];
  375.         os_byte(226, 0xD0, 0, retvals);
  376.         old226 = retvals[1];
  377.  
  378.         ioctl(0, TCGETA, &told);
  379.         tnew = told;
  380.         tnew.c_iflag &= ~(ICRNL | IXON);        /* ICRNL enables typing ^V^M */
  381.                                                 /* IXON enables typing ^S/^Q */
  382.         tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE);
  383.         tnew.c_cc[VMIN] = 1;            /* return after 1 char */
  384.         tnew.c_cc[VTIME] = 0;            /* don't wait */
  385.         ioctl(0, TCSETA, &tnew);
  386.     }
  387.     else
  388.     {
  389.         os_byte(4, old4, 0, retvals);
  390.         os_byte(225, old225, 0, retvals);
  391.         os_byte(226, old226, 0, retvals);
  392.         ioctl(0, TCSETA, &told);
  393.     }
  394. }
  395.  
  396. /*
  397.  * Try to get the current window size:
  398.  * 1. with an ioctl(), most accurate method
  399.  * 2. from the environment variables LINES and COLUMNS
  400.  * 3. from the termcap
  401.  * 4. keep using the old values
  402.  */
  403.     int
  404. mch_get_winsize()
  405. {
  406.     int            old_Rows = Rows;
  407.     int            old_Columns = Columns;
  408.     char        *p;
  409.  
  410.     Columns = 0;
  411.     Rows = 0;
  412.  
  413. /*
  414.  * 1. try using an ioctl. It is the most accurate method.
  415.  */
  416.     {
  417.         struct winsize    ws;
  418.  
  419.         if (ioctl(0, TIOCGWINSZ, &ws) == 0)
  420.         {
  421.             Columns = ws.ws_col;
  422.             Rows = ws.ws_row;
  423.         }
  424.     }
  425.  
  426. /*
  427.  * 2. get size from environment
  428.  */
  429.     if (Columns == 0 || Rows == 0)
  430.     {
  431.         if ((p = (char *)getenv("LINES")))
  432.             Rows = atoi(p);
  433.         if ((p = (char *)getenv("COLUMNS")))
  434.             Columns = atoi(p);
  435.     }
  436.  
  437. /*
  438.  * 3. try reading the termcap
  439.  */
  440.     if (Columns == 0 || Rows == 0)
  441.     {
  442.         extern void getlinecol();
  443.  
  444.         getlinecol();    /* get "co" and "li" entries from termcap */
  445.     }
  446.  
  447. /*
  448.  * 4. If everything fails, use the old values
  449.  */
  450.     if (Columns <= 0 || Rows <= 0)
  451.     {
  452.         Columns = old_Columns;
  453.         Rows = old_Rows;
  454.         return 1;
  455.     }
  456.     debug2("mch_get_winsize: %dx%d\n", (int)Columns, (int)Rows);
  457.  
  458.     Rows_max = Rows;                /* remember physical max height */
  459.  
  460.     check_winsize();
  461.     script_winsize();
  462.  
  463. /* if size changed: screenalloc will allocate new screen buffers */
  464.     return (0);
  465. }
  466.  
  467.     void
  468. mch_set_winsize()
  469. {
  470.     /* should try to set the window size to Rows and Columns */
  471. }
  472.  
  473.     int 
  474. call_shell(cmd, options)
  475.     char    *cmd;
  476.     int        options;        /* SHELL_FILTER if called by do_filter() */
  477.                             /* SHELL_COOKED if term needs cooked mode */
  478.                             /* SHELL_EXPAND if called by ExpandWildCards() */
  479. {
  480.     int        x;
  481.     char    newcmd[1024];
  482.  
  483.     flushbuf();
  484.  
  485.     if (options & SHELL_COOKED)
  486.         settmode(0);                 /* set to cooked mode */
  487.  
  488.     if (cmd == NULL)
  489.         x = system(p_sh);
  490.     else
  491.     {
  492.         sprintf(newcmd, "*%s", cmd);
  493.         x = system(newcmd);
  494.     }
  495.     if (x == 127)
  496.     {
  497.         emsg("Cannot execute shell sh");
  498.         msg_outchar('\n');
  499.     }
  500.     else if (x)
  501.     {
  502.         smsg("%d returned", x);
  503.         msg_outchar('\n');
  504.     }
  505.  
  506.     settmode(1);                         /* set to raw mode */
  507.     return (x ? FAIL : OK);
  508. }
  509.  
  510. /*
  511.  * The input characters are buffered to be able to check for a CTRL-C.
  512.  * This should be done with signals, but I don't know how to do that in
  513.  * a portable way for a tty in RAW mode.
  514.  */
  515.  
  516. #define INBUFLEN 50
  517. static unsigned char        inbuf[INBUFLEN];    /* internal typeahead buffer */
  518. static int                    inbufcount = 0;        /* number of chars in inbuf[] */
  519.  
  520.     static int
  521. Read(buf, maxlen)
  522.     char    *buf;
  523.     long    maxlen;
  524. {
  525.     if (inbufcount == 0)        /* if the buffer is empty, fill it */
  526.         fill_inbuf();
  527.     if (maxlen > inbufcount)
  528.         maxlen = inbufcount;
  529.     vim_memmove(buf, inbuf, (size_t)maxlen);
  530.     inbufcount -= maxlen;
  531.     if (inbufcount)
  532.         vim_memmove(inbuf, inbuf + maxlen, (size_t)inbufcount);
  533.     return (int)maxlen;
  534. }
  535.  
  536. /*
  537.  * check for CTRL-C typed by reading all available characters
  538.  */
  539.     void
  540. mch_breakcheck()
  541. {
  542.     if (RealWaitForChar(0L))        /* if characters available */
  543.         fill_inbuf();
  544. }
  545.  
  546.     static void
  547. fill_inbuf()
  548. {
  549.     int        len;
  550.  
  551.     if (inbufcount >= INBUFLEN)        /* buffer full */
  552.         return;
  553.  
  554.     for (len=0; len < INBUFLEN-inbufcount; len++)
  555.     {
  556.         int key;
  557.  
  558.         key = os_inkey(0);
  559.         if (key==-1)
  560.         {
  561.             break;
  562.         }
  563.         inbuf[inbufcount+len] = key;
  564.     }
  565.  
  566.     while (len-- > 0)
  567.     {
  568.         /*
  569.          * if a CTRL-C was typed, remove it from the buffer and set got_int
  570.          */
  571.         if (inbuf[inbufcount] == 3)
  572.         {
  573.             /* remove everything typed before the CTRL-C */
  574.             vim_memmove(inbuf, inbuf + inbufcount, (size_t)(len + 1));
  575.             inbufcount = 0;
  576.             got_int = TRUE;
  577.         }
  578.         ++inbufcount;
  579.     }
  580. }
  581.  
  582. /* 
  583.  * Wait "ticks" until a character is available from the keyboard or from inbuf[]
  584.  * ticks = -1 will block forever
  585.  */
  586.  
  587.     static int
  588. WaitForChar(ticks)
  589.     long ticks;
  590. {
  591.     if (inbufcount)        /* something in inbuf[] */
  592.         return 1;
  593.     return RealWaitForChar(ticks);
  594. }
  595.  
  596. /* 
  597.  * Wait "ticks" until a character is available from the keyboard
  598.  * ticks = -1 will block forever
  599.  */
  600.     static int
  601. RealWaitForChar(ticks)
  602.     long ticks;
  603. {
  604.     int    key;
  605.  
  606.     if (ticks == -1)
  607.     {
  608.         key = os_get();
  609.     }
  610.     else
  611.     {
  612.         key = os_inkey((int)(ticks/10));
  613.     }
  614. debug3("RWFC(%ld) got %d (%c)\n", ticks, key, key);
  615.     
  616.     if (key != -1)
  617.     {
  618.         /* Unfortunately the key has now been taken from the
  619.          * buffer, so we need to put it in outselves. It's a 
  620.          * shame, but the other way I can think of involves a
  621.          * keyboard scan, and this would return for SHIFT, etc.
  622.          */
  623.          if (inbufcount < INBUFLEN)
  624.          {
  625.              inbuf[inbufcount++] = key;
  626.         }
  627.     }
  628.     return (key != -1);
  629. }
  630.  
  631. /*
  632.  * ExpandWildCards() - this code does wild-card pattern matching using the shell
  633.  *
  634.  * Mool: return 0 for success, 1 for error (you may loose some memory) and
  635.  *       put an error message in *file.
  636.  *
  637.  * num_pat is number of input patterns
  638.  * pat is array of pointers to input patterns
  639.  * num_file is pointer to number of matched file names
  640.  * file is pointer to array of pointers to matched file names
  641.  * On Unix we do not check for files only yet
  642.  * list_notfound is ignored
  643.  */
  644.  
  645. extern char *mktemp __ARGS((char *));
  646. #ifndef SEEK_SET
  647. # define SEEK_SET 0
  648. #endif
  649. #ifndef SEEK_END
  650. # define SEEK_END 2
  651. #endif
  652.  
  653.     int
  654. ExpandWildCards(num_pat, pat, num_file, file, files_only, list_notfound)
  655.     int             num_pat;
  656.     char          **pat;
  657.     int            *num_file;
  658.     char         ***file;
  659.     int                files_only;
  660.     int                list_notfound;
  661. {
  662.     char    tmpname[TMPNAMELEN];
  663.     char    *command;
  664.     int        i;
  665.     int        dir;
  666.     size_t    len;
  667.     FILE    *fd;
  668.     char    *buffer;
  669.     char    *p;
  670.  
  671.     *num_file = 0;        /* default: no files found */
  672.     *file = (char **)"";
  673.  
  674.     /*
  675.      * If there are no wildcards, just copy the names to allocated memory.
  676.      * Saves a lot of time, because we don't have to run glob.
  677.      */
  678.     if (!have_wildcard(num_pat, pat))
  679.     {
  680.         *file = (char **)alloc(num_pat * sizeof(char *));
  681.         if (*file == NULL)
  682.         {
  683.             *file = (char **)"";
  684.             return 1;
  685.         }
  686.         for (i = 0; i < num_pat; i++)
  687.             (*file)[i] = strsave(pat[i]);
  688.         *num_file = num_pat;
  689.         return 0;
  690.     }
  691.  
  692. /*
  693.  * get a name for the temp file
  694.  */
  695.     strcpy(tmpname, TMPNAME2);
  696.     if (*mktemp(tmpname) == NUL)
  697.     {
  698.         emsg(e_notmp);
  699.         return 1;
  700.     }
  701.  
  702.     len = TMPNAMELEN + 10;
  703.     for (i = 0; i < num_pat; ++i)        /* count the length of the patterns */
  704.         len += strlen(pat[i]) + 1;
  705.     command = (char *)alloc(len);
  706.     if (command == NULL)
  707.         return 1;
  708.     strcpy(command, "glob >");            /* built the shell command */
  709.     strcat(command, tmpname);
  710.     for (i = 0; i < num_pat; ++i)
  711.     {
  712.         strcat(command, " ");
  713.         strcat(command, pat[i]);
  714.     }
  715.     i = call_shell(command, SHELL_EXPAND);    /* execute it */
  716.     vim_free(command);
  717.     if (i)                                    /* call_shell failed */
  718.     {
  719.         vim_remove((char_u *)tmpname);
  720.         mch_delay(1000L, TRUE);                /* give the user a chance to read
  721.                                                error messages */
  722.         must_redraw = CLEAR;                /* probably messed up screen */
  723.         return 1;
  724.     }
  725.  
  726. /*
  727.  * read the names from the file into memory
  728.  */
  729.      fd = fopen(tmpname, "r");
  730.     if (fd == NULL)
  731.     {
  732.         emsg(e_notopen);
  733.         return 1;
  734.     }
  735.  
  736.     fseek(fd, 0L, SEEK_END);
  737.     len = ftell(fd);                /* get size of temp file */
  738.     fseek(fd, 0L, SEEK_SET);
  739.     buffer = (char *)alloc(len + 1);
  740.     if (buffer == NULL)
  741.     {
  742.         vim_remove((char_u *)tmpname);
  743.         fclose(fd);
  744.         return 1;
  745.     }
  746.     i = fread(buffer, 1, len, fd);
  747.     fclose(fd);
  748.     vim_remove((char_u *)tmpname);
  749.     if (i != len)
  750.     {
  751.         emsg(e_notread);
  752.         vim_free(buffer);
  753.         return 1;
  754.     }
  755.  
  756.     buffer[len] = NUL;                    /* make sure the buffers ends in NUL */
  757.     i = 0;
  758.     for (p = buffer; p < buffer + len; ++p)
  759.         if (*p == NUL)                    /* count entry */
  760.             ++i;
  761.     if (len)
  762.         ++i;                            /* count last entry */
  763.  
  764.     *num_file = i;
  765.     *file = (char **)alloc(sizeof(char *) * i);
  766.     if (*file == NULL)
  767.     {
  768.         vim_free(buffer);
  769.         *file = (char **)"";
  770.         return 1;
  771.     }
  772.     p = buffer;
  773.  
  774.     for (i = 0; i < *num_file; ++i)
  775.     {
  776.         (*file)[i] = p;
  777.         while (*p && p < buffer + len)        /* skip entry */
  778.             ++p;
  779.         ++p;                                /* skip NUL */
  780.     }
  781.     for (i = 0; i < *num_file; ++i)
  782.     {
  783.         dir = (mch_isdir((*file)[i]));
  784.         if (dir < 0)            /* if file doesn't exist don't add '.' */
  785.             dir = 0;
  786.         p = alloc((unsigned)(strlen((*file)[i]) + 1 + dir));
  787.         if (p)
  788.         {
  789.             strcpy(p, (*file)[i]);
  790.             if (dir)
  791.                 strcat(p, ".");
  792.         }
  793.         (*file)[i] = p;
  794.     }
  795.     vim_free(buffer);
  796.     return 0;
  797. }
  798.  
  799.     int
  800. mch_has_wildcard(p)
  801.     char *p;
  802. {
  803.     return strpbrk(p, "*#") != NULL;
  804. }
  805.  
  806.     static int
  807. have_wildcard(num, file)
  808.     int        num;
  809.     char    **file;
  810. {
  811.     register int i;
  812.  
  813.     for (i = 0; i < num; i++)
  814.         if (mch_has_wildcard(file[i]))
  815.             return 1;
  816.     return 0;
  817. }
  818.